package ChessEngine;

import boardData.Board;

public class PieceSquareSimpleEvaluator extends SimpleEvaluator {
	/**
	 * Fuehrt die Bewertung fuer ein Board aus, und
	 * gibt den Wert der Bewertung zurueck. 
	 * 
	 * @param b Board das bewertet werden soll.
	 */
	@Override
	public int evaluate(Board b) {
		/*
		 * Reiner Materialwert der Figuren
		 */
		int materialCount = super.evaluate(b);
		int result = pieceSquareMaterialCount(b,materialCount);		
		return result;
	}
	
	/**
	 * PieceSquare-Material-Count der fuer die Positionen einer Figur auf dem Brett
	 * eine spezielle Bewertung zurueckliefert.
	 * @param b aktuelles Board, fuer welches die Positionen ausgewertet werden sollen
	 * @param materialCount anhand des Materialcounts wird bestimmt, ob fuer den Koenig die normale, oder 
	 *                      die Endspieltabelle verwendet wird.
	 * @return PieceSquare-Material-Count der fuer das aktuelle Board.
	 */
	private int pieceSquareMaterialCount(Board b,int materialCount) {																		
		/*
		 *  Wert der aktuellen Evaluation wird in sum gespeichert, Werte aus der 
		 *  Piece-Square-Matrix werden hinzuaddiert, oder subtrahiert.
		 */		
		int sum=0;								
		
		PieceSquareTables pcq = new PieceSquareTables();
		for(int i=21,sub=21;i<=98;i++){
			/*
			 *  Felder die nicht im gültigen Bereich sind zu überspringen!
			 *  Bsp: 29,30; 39,40; 49,50...
			 *  
			 *  sub rechnet die 21 bis 98er Werte auf 0-63 Array-Indizes runter, da
			 *  die Bewertungsmatrizen als int[8x8] gespeichert sind!!!
			 */
			
			if (((i)%10)==0)
				sub+=2;
			
			if ((((i+1)%10)==0) || (((i)%10)==0))
				continue;
			
			int diff=0;
			
			switch(b.getPiece(i)){						
				// Black
				case Pieces.PieceValues.BLACK_BISHOP:
					// Stimmt sub?? PRÜFEN!!!! Sollte funktionieren. Im Einzel-Arraytest gehts :-)
					sum += pcq.getBlackBishopEvaluation(i-sub);					
				break;									
					
				case Pieces.PieceValues.BLACK_KNIGHT:
					sum += pcq.getBlackKnightEvaluation(i-sub);
				break;
				
				case Pieces.PieceValues.BLACK_PAWN:
					sum += pcq.getBlackPawnEvaluation(i-sub);
				break;
					
				case Pieces.PieceValues.BLACK_QUEEN:
					sum += pcq.getBlackQueenEvaluation(i-sub);
				break;
					
				case Pieces.PieceValues.BLACK_ROOK:		
					sum += pcq.getBlackRookEvaluation(i-sub);
				break;
				
				case Pieces.PieceValues.BLACK_KING:
					diff = super.countWhiteScore(b);
					// Umstellen auf Endspiel-Koenig-Bewertung
					// Damit alles richtig erkannt wird, muss vom schwarzen Wert noch der weisse abgezogen werden!
					if (isEndGame(materialCount-diff))
						sum += pcq.getBlackKingEndGameEvaluation(i-sub);
					else
						sum += pcq.getBlackKingMiddleGameEvaluation(i-sub);
				break;
				
				////////////////////////////////////////////////////////////////////////////
				
				// White
				case Pieces.PieceValues.WHITE_BISHOP:
					sum += pcq.getWhiteBishopEvaluation(i-sub);					
				break;								
				
				case Pieces.PieceValues.WHITE_KNIGHT:
					sum += pcq.getWhiteKnightEvaluation(i-sub);
				break;
					
				case Pieces.PieceValues.WHITE_PAWN:
					sum += pcq.getWhitePawnEvaluation(i-sub);
				break;
					
				case Pieces.PieceValues.WHITE_QUEEN:
					sum += pcq.getWhiteQueenEvaluation(i-sub);
				break;
					
				case Pieces.PieceValues.WHITE_ROOK:
					sum += pcq.getWhiteRookEvaluation(i-sub);
				break;
				
				case Pieces.PieceValues.WHITE_KING:
					diff = super.countBlackScore(b);
					// Umstellen auf Endspiel-Koenig-Bewertung?
					// Damit alles richtig erkannt wird, muss vom weissen Wert noch der schwarze abgezogen werden!
					if (isEndGame(materialCount-diff))
						sum += pcq.getWhiteKingEndGameEvaluation(i-sub);
					else
						sum += pcq.getWhiteKingMiddleGameEvaluation(i-sub);
				break;
			}
		}
		return sum;
	}

	private boolean isEndGame(int sum) {
		boolean endGame = false;
		
		if (sum <= (AbstractEvalutor.KING_SCORE + AbstractEvalutor.QUEEN_SCORE))
			endGame = true;		
		else
			endGame = false;		
		
		return endGame;
	}

}
